#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
#include <xcb/xproto.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

#define WIDTH  800
#define HEIGHT 600

int main() {
    const char *display_name = ":1"; // 指定要连接的 X11 服务器地址和显示号
    xcb_connection_t *connection = xcb_connect_to_display_with_auth_info(display_name, NULL, NULL);
    
    if (xcb_connection_has_error(connection)) {
        fprintf(stderr, "Error connecting to X server %s\n", display_name);
        return 1;
    }

    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
    xcb_window_t window = xcb_generate_id(connection);

    uint32_t value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t value_list[] = {screen->black_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS};

    xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, WIDTH, HEIGHT, 0,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list);

    xcb_map_window(connection, window);
    xcb_flush(connection);
    //ok not to black

    xcb_dri3_open_cookie_t dri3_cookie = xcb_dri3_open(connection, window, 0);
    xcb_dri3_open_reply_t *dri3_reply = xcb_dri3_open_reply(connection, dri3_cookie, NULL);
    if (!dri3_reply) {
        fprintf(stderr, "Cannot open DRI3 connection\n");
        return -1;
    }

    int dri3_fd = dri3_reply->nfd > 0 ? xcb_dri3_open_reply_fds(connection, dri3_reply)[0] : -1;
    free(dri3_reply);

    if (dri3_fd < 0) {
        fprintf(stderr, "Cannot get DRI3 file descriptor\n");
        return -1;
    }


    xcb_pixmap_t pixmap = xcb_generate_id(connection);
    xcb_dri3_pixmap_from_buffer(connection, pixmap, window, WIDTH * HEIGHT * 4, WIDTH, HEIGHT, WIDTH * 4, 24, 32, dri3_fd);

    xcb_dri3_buffer_from_pixmap_cookie_t cookie = xcb_dri3_buffer_from_pixmap(connection, pixmap);
    xcb_dri3_buffer_from_pixmap_reply_t *reply = xcb_dri3_buffer_from_pixmap_reply(connection, cookie, NULL);
    if (!reply) {
        fprintf(stderr, "Cannot get buffer from pixmap\n");
        return -1;
    }
    return 0;

    int buffer_fd = xcb_dri3_buffer_from_pixmap_reply_fds(connection, reply)[0];
    free(reply);

    uint32_t *buffer = malloc(WIDTH * HEIGHT * 4);
    if (!buffer) {
        fprintf(stderr, "Cannot allocate buffer\n");
        return -1;
    }

    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            buffer[y * WIDTH + x] = 0x00FF00FF; // ARGB: Green with full alpha
        }
    }

    if (pwrite(buffer_fd, buffer, WIDTH * HEIGHT * 4, 0) == -1) {
        fprintf(stderr, "Cannot write to buffer\n");
        free(buffer);
        return -1;
    }

    free(buffer);

    xcb_present_pixmap(connection, window, pixmap, 0, 0, XCB_NONE, XCB_NONE, 0,0,0,0, 0, 0, 0, 0, 0, NULL);

    xcb_flush(connection);

    xcb_generic_event_t *event;
    while ((event = xcb_wait_for_event(connection))) {
        if ((event->response_type & ~0x80) == XCB_KEY_PRESS) {
            break;
        }
        free(event);
    }

    munmap(buffer, WIDTH * HEIGHT * 4);
    close(dri3_fd);
    xcb_disconnect(connection);

    return 0;
}

